from fredapi import Fred
from requests import get
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly.express as px
Gallup_df=pd.read_csv('data-y7uQi.csv')
Gallup_df.head()
| X.1 | Index | |
|---|---|---|
| 0 | Jan 1 1996 | 1 |
| 1 | Jul 1 1996 | 13 |
| 2 | Aug 1 1996 | 18 |
| 3 | Oct 1 1996 | 23 |
| 4 | Jan 1 1997 | 17 |
Gallup_df2=pd.read_csv('data-Yv6Vx.csv')
Gallup_df2.head()
| X.1 | Getting better | Getting worse | Same (vol.) | No opinion | |
|---|---|---|---|---|---|
| 0 | 2024 Dec 2 | 38 | 52 | 7 | 3 |
| 1 | 2024 Nov 6 | 36 | 55 | 5 | 4 |
| 2 | 2024 Oct 1 | 32 | 62 | 4 | 2 |
| 3 | 2024 Sep 3 | 32 | 62 | 5 | 2 |
| 4 | 2024 Aug 1 | 31 | 63 | 3 | 2 |
fred = Fred(api_key='e7adfc69642678c50ce3c1126d8e3f3d')
series_list = {
"NGDPSAXDCUSQ": "Nominal GDP",
"FEDFUNDS": "Interest Rates",
"CPIAUCSL": "CPI(Inflation)",
"UNRATE": "Unemployment Rate",
"SPCS20RSA":"Home Price Index",
"CES0500000003":"Average Hourly Earnings",
"CPIUFDNS":"Cost of living Index"}
data = {}
for series_id, column_name in series_list.items():
data[column_name] = fred.get_series(series_id)
Fred_Data = pd.DataFrame(data)
Fred_Data.head()
| Nominal GDP | Interest Rates | CPI(Inflation) | Unemployment Rate | Home Price Index | Average Hourly Earnings | Cost of living Index | |
|---|---|---|---|---|---|---|---|
| 1913-01-01 | NaN | NaN | NaN | NaN | NaN | NaN | 9.7 |
| 1913-02-01 | NaN | NaN | NaN | NaN | NaN | NaN | 9.6 |
| 1913-03-01 | NaN | NaN | NaN | NaN | NaN | NaN | 9.6 |
| 1913-04-01 | NaN | NaN | NaN | NaN | NaN | NaN | 9.7 |
| 1913-05-01 | NaN | NaN | NaN | NaN | NaN | NaN | 9.6 |
Gallup_df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 252 entries, 0 to 251 Data columns (total 2 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 X.1 252 non-null object 1 Index 252 non-null int64 dtypes: int64(1), object(1) memory usage: 4.1+ KB
Gallup_df.describe()
| Index | |
|---|---|
| count | 252.000000 |
| mean | -4.519841 |
| std | 25.956975 |
| min | -72.000000 |
| 25% | -21.000000 |
| 50% | -5.000000 |
| 75% | 14.250000 |
| max | 56.000000 |
Gallup_df2.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 85 entries, 0 to 84 Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 X.1 85 non-null object 1 Getting better 85 non-null int64 2 Getting worse 85 non-null int64 3 Same (vol.) 85 non-null int64 4 No opinion 85 non-null object dtypes: int64(3), object(2) memory usage: 3.4+ KB
Gallup_df2.describe()
| Getting better | Getting worse | Same (vol.) | |
|---|---|---|---|
| count | 85.000000 | 85.000000 | 85.000000 |
| mean | 36.800000 | 57.341176 | 4.494118 |
| std | 12.836703 | 13.986859 | 1.452613 |
| min | 13.000000 | 33.000000 | 1.000000 |
| 25% | 26.000000 | 45.000000 | 3.000000 |
| 50% | 33.000000 | 61.000000 | 5.000000 |
| 75% | 49.000000 | 69.000000 | 5.000000 |
| max | 61.000000 | 85.000000 | 9.000000 |
Fred_Data.info()
<class 'pandas.core.frame.DataFrame'> DatetimeIndex: 1345 entries, 1913-01-01 to 2025-01-01 Freq: MS Data columns (total 7 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Nominal GDP 299 non-null float64 1 Interest Rates 847 non-null float64 2 CPI(Inflation) 936 non-null float64 3 Unemployment Rate 925 non-null float64 4 Home Price Index 299 non-null float64 5 Average Hourly Earnings 227 non-null float64 6 Cost of living Index 1344 non-null float64 dtypes: float64(7) memory usage: 84.1 KB
Fred_Data.describe()
| Nominal GDP | Interest Rates | CPI(Inflation) | Unemployment Rate | Home Price Index | Average Hourly Earnings | Cost of living Index | |
|---|---|---|---|---|---|---|---|
| count | 2.990000e+02 | 847.000000 | 936.000000 | 925.000000 | 299.000000 | 227.000000 | 1344.000000 |
| mean | 1.916354e+06 | 4.609020 | 121.519631 | 5.681622 | 189.786853 | 26.174626 | 90.110816 |
| std | 1.925671e+06 | 3.565496 | 87.094194 | 1.708949 | 58.904567 | 4.307423 | 89.143996 |
| min | 7.020700e+04 | 0.050000 | 21.480000 | 2.500000 | 100.589697 | 20.050000 | 9.400000 |
| 25% | 2.398569e+05 | 1.825000 | 32.432500 | 4.400000 | 144.313548 | 22.750000 | 17.000000 |
| 50% | 1.201540e+06 | 4.290000 | 109.000000 | 5.500000 | 178.839344 | 25.090000 | 36.000000 |
| 75% | 3.365420e+06 | 6.155000 | 194.000000 | 6.700000 | 212.618196 | 29.385000 | 156.350000 |
| max | 7.343728e+06 | 19.100000 | 317.685000 | 14.800000 | 335.827481 | 35.870000 | 333.566000 |
# changing column type to date
Gallup_df['X.1']=pd.to_datetime(Gallup_df['X.1'])
# Setting Date as the index for the DF
Gallup_df.set_index('X.1', inplace=True)
Gallup_df.index.name = 'Date'
Gallup_df.info()
<class 'pandas.core.frame.DataFrame'> DatetimeIndex: 252 entries, 1996-01-01 to 2024-12-02 Data columns (total 1 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Index 252 non-null int64 dtypes: int64(1) memory usage: 3.9 KB
# changing column type to date
Gallup_df2['X.1']=pd.to_datetime(Gallup_df2['X.1'])
# Setting Date as the index for the DF
Gallup_df2.set_index('X.1', inplace=True)
Gallup_df2.index.name = 'Date'
# Droping 'No Opinon' column because it had a lot of null and missing data. Was also irrelevant for analysis.
Gallup_df2=Gallup_df2.drop('No opinion',axis=1)
Gallup_df2.info()
<class 'pandas.core.frame.DataFrame'> DatetimeIndex: 85 entries, 2024-12-02 to 2018-01-02 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Getting better 85 non-null int64 1 Getting worse 85 non-null int64 2 Same (vol.) 85 non-null int64 dtypes: int64(3) memory usage: 2.7 KB
#droping all rows with missing data.
df=Fred_Data.dropna()
df.info()
<class 'pandas.core.frame.DataFrame'> DatetimeIndex: 74 entries, 2006-04-01 to 2024-07-01 Freq: 3MS Data columns (total 7 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Nominal GDP 74 non-null float64 1 Interest Rates 74 non-null float64 2 CPI(Inflation) 74 non-null float64 3 Unemployment Rate 74 non-null float64 4 Home Price Index 74 non-null float64 5 Average Hourly Earnings 74 non-null float64 6 Cost of living Index 74 non-null float64 dtypes: float64(7) memory usage: 4.6 KB
df.describe()
| Nominal GDP | Interest Rates | CPI(Inflation) | Unemployment Rate | Home Price Index | Average Hourly Earnings | Cost of living Index | |
|---|---|---|---|---|---|---|---|
| count | 7.400000e+01 | 74.000000 | 74.000000 | 74.000000 | 74.000000 | 74.000000 | 74.000000 |
| mean | 4.796686e+06 | 1.526892 | 243.887284 | 5.954054 | 203.355096 | 25.970270 | 249.272905 |
| std | 1.109052e+06 | 1.931459 | 29.979955 | 2.314764 | 56.526588 | 4.138085 | 35.365768 |
| min | 3.438356e+06 | 0.050000 | 200.700000 | 3.400000 | 137.146012 | 20.150000 | 193.700000 |
| 25% | 3.829992e+06 | 0.110000 | 219.573000 | 4.050000 | 157.123970 | 22.772500 | 221.190000 |
| 50% | 4.585176e+06 | 0.335000 | 237.575000 | 5.000000 | 193.155014 | 24.950000 | 246.770500 |
| 75% | 5.427254e+06 | 2.370000 | 256.897750 | 7.750000 | 220.776602 | 28.380000 | 260.700750 |
| max | 7.343728e+06 | 5.330000 | 313.534000 | 14.800000 | 331.287120 | 35.070000 | 330.561000 |
# Cutting off data at 2015 and up.
Gallup_df= Gallup_df[Gallup_df.index>='2015-01-01']
Gallup_df.info()
<class 'pandas.core.frame.DataFrame'> DatetimeIndex: 88 entries, 2015-01-01 to 2024-12-02 Data columns (total 1 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Index 88 non-null int64 dtypes: int64(1) memory usage: 1.4 KB
Gallup_df2.info()
<class 'pandas.core.frame.DataFrame'> DatetimeIndex: 85 entries, 2024-12-02 to 2018-01-02 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Getting better 85 non-null int64 1 Getting worse 85 non-null int64 2 Same (vol.) 85 non-null int64 dtypes: int64(3) memory usage: 2.7 KB
# Cutting off data at 2015 and up.
df = df[df.index >= '2015-01-01']
# Creating new Rate of change columns.
df['GDP Rate (%)'] = df['Nominal GDP'].pct_change()*100
df['Inflation Rate (%)'] = df['CPI(Inflation)'].pct_change()*100
df['Home Price Rate(%)']=df['Home Price Index'].pct_change()*100
df['Cost of living Rate(%)']=df['Cost of living Index'].pct_change()*100
df['Wage Growth Rate(%)']=df['Average Hourly Earnings'].pct_change()*100
df.info()
<class 'pandas.core.frame.DataFrame'> DatetimeIndex: 39 entries, 2015-01-01 to 2024-07-01 Freq: 3MS Data columns (total 12 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Nominal GDP 39 non-null float64 1 Interest Rates 39 non-null float64 2 CPI(Inflation) 39 non-null float64 3 Unemployment Rate 39 non-null float64 4 Home Price Index 39 non-null float64 5 Average Hourly Earnings 39 non-null float64 6 Cost of living Index 39 non-null float64 7 GDP Rate (%) 38 non-null float64 8 Inflation Rate (%) 38 non-null float64 9 Home Price Rate(%) 38 non-null float64 10 Cost of living Rate(%) 38 non-null float64 11 Wage Growth Rate(%) 38 non-null float64 dtypes: float64(12) memory usage: 4.0 KB
# Final data
Gallup_df.head()
| Index | |
|---|---|
| Date | |
| 2015-01-01 | 7 |
| 2016-01-01 | -9 |
| 2017-01-01 | 23 |
| 2017-12-01 | 13 |
| 2018-01-01 | 18 |
# Final data
Gallup_df2.head()
| Getting better | Getting worse | Same (vol.) | |
|---|---|---|---|
| Date | |||
| 2024-12-02 | 38 | 52 | 7 |
| 2024-11-06 | 36 | 55 | 5 |
| 2024-10-01 | 32 | 62 | 4 |
| 2024-09-03 | 32 | 62 | 5 |
| 2024-08-01 | 31 | 63 | 3 |
# Final data
df.head()
| Nominal GDP | Interest Rates | CPI(Inflation) | Unemployment Rate | Home Price Index | Average Hourly Earnings | Cost of living Index | GDP Rate (%) | Inflation Rate (%) | Home Price Rate(%) | Cost of living Rate(%) | Wage Growth Rate(%) | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2015-01-01 | 4515882.5 | 0.11 | 234.747 | 5.7 | 175.047514 | 24.75 | 246.538 | NaN | NaN | NaN | NaN | NaN |
| 2015-04-01 | 4569946.0 | 0.12 | 236.222 | 5.4 | 177.710269 | 24.89 | 246.121 | 1.197186 | 0.628336 | 1.521161 | -0.169142 | 0.565657 |
| 2015-07-01 | 4600406.5 | 0.13 | 238.034 | 5.2 | 179.388543 | 25.01 | 247.003 | 0.666540 | 0.767075 | 0.944388 | 0.358360 | 0.482121 |
| 2015-10-01 | 4608784.5 | 0.12 | 237.733 | 5.0 | 181.921952 | 25.20 | 249.052 | 0.182114 | -0.126453 | 1.412247 | 0.829545 | 0.759696 |
| 2016-01-01 | 4631483.5 | 0.34 | 237.652 | 4.8 | 184.681531 | 25.37 | 248.631 | 0.492516 | -0.034072 | 1.516903 | -0.169041 | 0.674603 |
#visualizations
#visualization (graphing gallup poll on economic confidence index)
fig_1=px.line(Gallup_df,range_y=[-60,50], width=1000, height=500,
title='FIGURE #1<br>Gallup Economic Confidence Index, 2015-2024<br><sup>Among U.S. adults')
fig_1.add_vline(x='2020-01-01', line_color="brown",line_dash="dot")
fig_1.add_annotation(text="Covid-19", x='2019-09-01',y=10,font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False,
hovertext='The outbreak of the COVID-19 global pandemic and the subsequent lockdowns')
#visualization (graphing gallup poll on economic outlook)
fig_2=px.line(Gallup_df2, y=Gallup_df2.columns[0:], height=500,
title='FIGURE #2<br>Economic Confidence -- Economic Outlook,2018-2024<br><sup>Right now, do you think that economic conditions in the country as a whole are getting better or getting worse?')
fig_2.add_vline(x='2020-01-01', line_color="brown",line_dash="dot")
fig_2.add_annotation(text="Covid-19", x='2019-10-01',y=80, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False,
hovertext='The outbreak of the COVID-19 global pandemic and the subsequent lockdowns')
#visualization (graphing Domestic GDP)
fig_3=px.line(df, y=['Nominal GDP'],width=900, height=600,
title= 'FIGURE #3<br>Nominal Gross Domestic Product for United States, 2015-2024<br><sup>FRED Series ID:(NGDPSAXDCUSQ)')
fig_3.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_3.add_annotation(text="Covid-19", x='2019-09-01',y=6500000, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_3.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_3.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=7000000, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
#visualization (graphing rate of change for GDP)
fig_3A=px.line(df, y=['GDP Rate (%)'],width=900, height=600,
title= 'FIGURE #3A<br>GDP Growth Rate, 2015-2024<br><sup>Percent Change in GDP from previous observation to current')
fig_3A.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_3A.add_annotation(text="Covid-19", x='2019-09-01',y=5, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_3A.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_3A.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=7, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
#visualization (graphing Iinterest rates)
fig_4=px.line(df, y='Interest Rates', width=900, height=600,
title= 'FIGURE #4<br>Federal Funds Effective Rate (Interest Rate), 2015-2024 <br><sup>FRED Series ID:(FEDFUNDS)')
fig_4.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_4.add_annotation(text="Covid-19", x='2019-09-01',y=4.5, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_4.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_4.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=4.5, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
#visualization (graphing Consumer price index)
fig_5=px.line(df, y='CPI(Inflation)',width=900, height=600,
title= 'FIGURE #5<br>Consumer Price Index for All Urban Consumers (Inflation), 2015-2024 <br><sup>FRED Series ID:(CPIAUCSL)')
fig_5.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_5.add_annotation(text="Covid-19", x='2019-09-01',y=290, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_5.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_5.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=300, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
#visualization (graphing Rate of change for CPI(inflation))
fig_6=px.line(df, y='Inflation Rate (%)', width=900, height=600,
title= 'FIGURE #6<br>Rate of Inflation, 2015-2024 <br><sup>Percent Change in CPI from previous observation to current.')
fig_6.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_6.add_annotation(text="Covid-19", x='2019-09-01',y=1.5, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_6.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_6.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=.5, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
#visualization (graphing unemployment rate)
fig_7=px.line(df, y='Unemployment Rate', width=900, height=600,
title= 'FIGURE #7<br>Unemployment Rate, 2015-2024 <br><sup>FRED Series ID:(UNRATE)')
fig_7.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_7.add_annotation(text="Covid-19", x='2019-09-01',y=12, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_7.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_7.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=10, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
#visualization (graphing home price index)
fig_8=px.line(df, y='Home Price Index',width=900, height=600,
title= 'FIGURE #8<br>S&P CoreLogic Case-Shiller 20-City Composite Home Price Index(Home price Index), 2015-2024<br><sup>FRED Series ID:(SPCS20RSA)')
fig_8.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_8.add_annotation(text="Covid-19", x='2019-09-01',y=300, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_8.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_8.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=250, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
#visualization (graphing cost of living: food)
fig_9=px.line(df,y='Cost of living Index', width=900, height=600,
title= 'FIGURE #9<br>Consumer Price Index for All Urban Consumers(Cost of living Index: Food Prices), 2015-2024<br><sup>FRED Series ID:(CPIUFDNS)')
fig_9.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_9.add_annotation(text="Covid-19", x='2019-09-01',y=300, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_9.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_9.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=270, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
#visualization (graphing Wage Growth)
fig_10=px.line(df,y='Average Hourly Earnings',width=900, height=600,
title= 'FIGURE #10<br>Average Hourly Earnings of All Employees(Wage Growth), 2015-2024 <br><sup>FRED Series ID:(CES0500000003)')
fig_10.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_10.add_annotation(text="Covid-19", x='2019-09-01',y=33, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_10.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_10.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=30, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
#visualization (graphing rate of change for home prices, cost of living, wage growth)
fig_11=px.line(df[df.index>= '2018-01-01'],y=['Home Price Rate(%)','Cost of living Rate(%)','Wage Growth Rate(%)'],width=1000, height=500,
title='FIGURE #11<br>Rate of change for Home Prices, Cost of Living, and Wage Growth,2019-2024<br><sup>Percent Change in Wage Growth, Cost of living Index, and Home price Index from previous observation to current')
fig_11.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_11.add_annotation(text="Covid-19", x='2019-09-01',y=5, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_11.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_11.add_annotation(text="Intrest Rate Hikes", x='2021-09-01',y=-1, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
print('')
The U.S. economy has undergone significant fluctuations over the past four to five years, shaped by the COVID-19 pandemic, government intervention, and subsequent economic adjustments. While macroeconomic indicators such as GDP growth, unemployment rates, and inflation provide a structured narrative of crisis, recovery, and stabilization, public perception has often diverged from these trends. Despite expert assessments suggesting a strong economic rebound, consumer confidence has remained historically low.
This analysis explores the disconnect between economic data and public sentiment by examining key macroeconomic indicators alongside survey data. Using data from the Federal Reserve Economic Data (FRED) database and Gallup polls, we assess why many Americans continue to feel pessimistic about the economy, even as traditional economic metrics suggest improvement.
When looking from an expert's perspective and at macroeconomic figures, we see a certain narrative about the past four to five years. During early 2020 (marked by the brown dotted line), the global outbreak of COVID and subsequent lockdowns had a significant impact. Unemployment rates skyrocketed, reaching a high of 14% in April 2020 (FIGURE #7). Economic activity came to a halt, causing GDP to decline for the first time since 2008, contracting by 8.34% between January 2020 and April 2020 (FIGURES #3 & #3A). Due to the lack of demand, prices fell, leading to deflation, with inflation decreasing by 1.07% in April 2020 (FIGURE #6). In response, the Federal Reserve cut interest rates to stimulate economic activity, lowering them to 0.5% in April 2020 (FIGURE #4). However, the only way to jump-start an economy in this condition was through massive stimulus. The U.S. government printed a vast amount of money and increased the money supply, subsidizing almost every aspect of the economy.
However, such drastic actions had consequences. The large influx of cash that kept the economy from collapsing also caused the post-lockdown economy to overheat. We see both the CPI and inflation rates surge, rising from a monthly rate of -1.07% in April 2020 to 2.25% in April 2022 (FIGURES #5 & #6). During this period (between the brown and green lines), unemployment dropped to near record lows of 3.5% in 2022, near-zero interest rates fueled GDP growth by 8.77% between its low in April 2020 and July 2020 (FIGURE #3), and alongside these developments, inflation became uncontrolled.
At this point, the nation had overcome the challenge of restarting the economy but now faced an overheated economy. To slow down this runaway economic surge, the Federal Reserve raised interest rates (marked by the green dotted line) from 0.08% at the beginning of 2022 to 4.33% by the end of the year, eventually peaking at 5.33% in October 2023 (FIGURE #4). These record-high interest rates were effective. Inflation gradually declined closer to its natural rate, falling from a monthly rate of 2.25% in April 2022 to 0.83% in January 2023 (FIGURE #6). Additionally, the Fed managed a "soft landing"—cooling down the economy without triggering a recession. GDP continued to grow at a monthly rate of around 2% from October 2020 to the present (FIGURES #3 & #3A), unemployment remained low at approximately 3.7% (FIGURE #7), and soon, interest rates are expected to return to historical norms. For economists and world leaders, this is considered a successful outcome. From the chaos of the COVID lockdowns to an overheated economy, the U.S. emerged in relatively strong shape, with low unemployment and record-high GDP growth. The same cannot be said for many European countries, which continue to struggle with uncontrolled inflation and mild recessions. This is the mainstream narrative among experts, and while it is not entirely incorrect, it omits critical details.
fig_3.show()
fig_3A.show()
fig_4.show()
fig_5.show()
fig_6.show()
fig_7.show()
Although headline macroeconomic figures and expert analyses suggest that the U.S. has largely recovered from the global economic shocks of the COVID pandemic, public sentiment tells a different story. According to a Gallup public opinion poll on the economic confidence index, public confidence in the economy dropped from 41 points in February 2020 to -22 in April 2020. This sentiment remained around an average index value of -10 points until the end of 2021. However, by June 2022—when most other economic indicators suggested recovery and stabilization—the public economic confidence index fell to a new low of -55 points. This pessimism persisted, averaging around -30 points through the end of 2024 (FIGURE #1).
Another Gallup poll on economic confidence outlook, which measures whether people expect the economy to improve or worsen, further supports this negative sentiment. In February 2020, 61% of Americans expected the economy to improve, while 33% expected it to worsen, with 5% believing it would stay the same. By April 2020, those figures had reversed, with only 22% expecting improvement and 74% expecting worsening conditions. While sentiment improved slightly over time—reaching its most optimistic point in April 2021 with 47% expecting improvement and 46% expecting deterioration—this trend reversed. By June 2022, economic outlook reached its most pessimistic point, with 85% expecting worsening conditions and only 13% expecting improvement. These sentiments have remained largely negative, with an average of 68% expecting worse economic conditions and only 25% expecting improvement (FIGURE #2). This widespread pessimism contrasts sharply with expert opinions and macroeconomic indicators and played a decisive role in the 2024 election outcome.
fig_1.show()
fig_2.show()
A significant portion of this disconnect in public opinion can be attributed to the widening gap between the cost of living and real wages. The cost of living can be divided into short-term, day-to-day expenses and long-term financial commitments and investments. To represent short-term costs, we look at food prices using the Consumer Price Index for All Urban Consumers (FIGURE #9), and for long-term costs, we examine home prices using the Composite Home Price Index (FIGURE #8). To capture wages, we analyze Average Hourly Earnings of All Employees (FIGURE #10). Examining the growth rates of these three indices before 2020, they remained relatively close, growing at a monthly rate between 0% and 1.3% (FIGURE #11). However, post-2020, these growth rates diverged significantly.
Initially, wages experienced a dramatic increase, from a monthly growth rate of 0.74% in January 2020 to 5.52% in April 2020 (FIGURE #11), driven by government stimulus checks and the Paycheck Protection Program (PPP), which allowed employers to continue paying workers. However, this wage growth was short-lived. Once the first wave of stimulus ended, wages declined sharply, with growth rates falling from 5.52% in April 2020 to -2.09% in July 2020 (FIGURE #11), erasing most of the gains. Wage growth then stabilized at 0.54% in October 2020 and remained around 1% for the next 3–4 years, showing no significant improvement (FIGURE #11).
The cost of living, however, followed a different trajectory. Food prices initially spiked due to increased demand and supply chain disruptions, with growth rates rising from 0.54% in January to 2.18% in April 2020 (FIGURE #11). After this spike, food price growth declined to 0.78% in July, hitting a low of 0.35% in October 2020 (FIGURE #11). However, unlike wages, which saw negative growth, food prices never reversed to undo their increase. After October 2020, food price growth steadily rose, peaking at 3.28% in July 2022. From April 2021 to January 2023, food prices grew at an average rate of 2.3%, compared to an average wage growth rate of around 1% during the same period (FIGURE #11). Since January 2023, food prices have continued growing at a rate similar to wages.
For long-term living costs, the disparity is even starker. In July 2020, home prices skyrocketed, with growth rates jumping from 0.91% monthly in July 2020 to 5.18% in October 2020. Over the next two years, home prices continued growing at around 5% monthly until April 2022 (FIGURE #11), leading to an almost 40% increase in home prices nationwide (FIGURE #8). This surge also drove up rents and housing costs across the board. While home price growth slowed, dropping to -2.29% in October 2022 and stabilizing at 2.24% in July 2023 (FIGURE #11), this decrease was not nearly enough to offset the massive price hikes of the previous two years.
The growing disconnect between wage stagnation and skyrocketing living costs explains why so many people perceive the economy as being in crisis. Over the past four to five years, while inflation and living costs surged and remained high, wages failed to keep pace. Experts may declare inflation "solved" now that growth rates have stabilized, but they overlook the immense gap created between wages and living costs. This gap and its impact on quality of life are the primary reasons behind the disconnect in public sentiment.
fig_8.show()
fig_9.show()
fig_10.show()
fig_11.show()
The research and analysis presented in this project provide only a surface-level exploration of the disconnect between macroeconomic indicators and public sentiment. Due to the scope and limitations of this research project, several factors that may contribute to this disparity remain unexplored. A more comprehensive analysis would require a deeper investigation into additional factors that shape public perception and economic performance. Below are key research questions to consider for gaining a fuller understanding of this issue.